package com.witmore.neutron.ai.cognitive.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * Redis分布式锁实现 (简化版本)
 * Author: 豆子高
 * Date: 2025/1/15
 * 
 * 注意：这是一个简化实现，生产环境建议使用 Redisson 或其他成熟的分布式锁框架
 */
@Slf4j
@Service
public class RedisDistributedLock implements DistributedLock {

    // 使用本地锁作为简化实现，生产环境需要替换为真正的Redis分布式锁
    private final java.util.concurrent.ConcurrentHashMap<String, String> lockMap = new java.util.concurrent.ConcurrentHashMap<>();

    private static final String LOCK_PREFIX = "session_usage_lock:";

    // 线程本地变量存储锁标识
    private final ThreadLocal<String> lockFlag = new ThreadLocal<>();

    @Override
    public boolean tryLock(String lockKey, long timeout, TimeUnit unit) {
        return tryLock(lockKey, 0, timeout, unit);
    }

    @Override
    public boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) {
        String lockId = UUID.randomUUID().toString();
        String fullKey = LOCK_PREFIX + lockKey;
        
        long waitTimeMillis = unit.toMillis(waitTime);
        long startTime = System.currentTimeMillis();
        
        while (System.currentTimeMillis() - startTime < waitTimeMillis) {
            // 简化实现：使用 ConcurrentHashMap 的 putIfAbsent 模拟分布式锁
            String existingValue = lockMap.putIfAbsent(fullKey, lockId);
            if (existingValue == null) {
                lockFlag.set(lockId);
                log.debug("获取分布式锁成功: {}, lockId: {}", lockKey, lockId);
                
                // 启动一个线程来处理锁的自动过期（简化实现）
                scheduleExpiration(fullKey, lockId, unit.toMillis(leaseTime));
                return true;
            }
            
            // 短暂等待后重试
            try {
                Thread.sleep(ThreadLocalRandom.current().nextLong(10, 50));
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.warn("等待获取锁时被中断: {}", lockKey);
                return false;
            }
        }
        
        log.warn("获取分布式锁超时: {}, waitTime: {}ms", lockKey, waitTimeMillis);
        return false;
    }

    private void scheduleExpiration(String lockKey, String lockId, long expireTimeMillis) {
        // 简化的过期处理，生产环境应该使用 ScheduledExecutorService
        java.util.Timer timer = new java.util.Timer(true);
        timer.schedule(new java.util.TimerTask() {
            @Override
            public void run() {
                String currentValue = lockMap.get(lockKey);
                if (lockId.equals(currentValue)) {
                    lockMap.remove(lockKey, lockId);
                    log.debug("锁自动过期: {}", lockKey);
                }
            }
        }, expireTimeMillis);
    }

    @Override
    public void unlock(String lockKey) {
        String lockId = lockFlag.get();
        if (lockId == null) {
            log.warn("尝试释放未持有的锁: {}", lockKey);
            return;
        }
        
        String fullKey = LOCK_PREFIX + lockKey;
        try {
            // 简化实现：检查并删除锁
            boolean removed = lockMap.remove(fullKey, lockId);
            if (removed) {
                log.debug("释放分布式锁成功: {}, lockId: {}", lockKey, lockId);
            } else {
                log.warn("释放分布式锁失败，锁可能已过期或被其他线程持有: {}, lockId: {}", lockKey, lockId);
            }
        } finally {
            lockFlag.remove();
        }
    }

    @Override
    public <T> T executeWithLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit, LockTask<T> task) throws Exception {
        boolean locked = tryLock(lockKey, waitTime, leaseTime, unit);
        if (!locked) {
            throw new RuntimeException("获取分布式锁失败: " + lockKey);
        }
        
        try {
            return task.execute();
        } finally {
            unlock(lockKey);
        }
    }
}